package com.transfiguro.datamodel.csmodels;

import com.transfiguro.datamodel.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;


public class CSMethod {
    private final Logger logger = LoggerFactory.getLogger(CSMethod.class);
    private String methodName;
    private String accessModifier;
    private String returnType;
    private List<CSVariable> inputParameters;
    private String methodBody;
    private CSXMLComment comment;
    private List<Statement> statements;
    private boolean isInterfaceMethod;
    private boolean isSynchronized;
    private double conversionTime;

    public CSMethod() {
        statements = new ArrayList<Statement>();
    }

    public void addStatement(final Statement statement) {
        statements.add(statement);
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(final String methodName) {
        this.methodName = methodName;
    }

    public String getAccessModifier() {
        return accessModifier;
    }

    public void setAccessModifier(final String accessModifier) {
        this.accessModifier = accessModifier;
    }

    public String getReturnType() {
        return returnType;
    }

    public void setReturnType(final String returnType) {
        this.returnType = returnType;
    }

    public List<CSVariable> getInputParameters() {
        return inputParameters;
    }

    public void setInputParameters(final List<CSVariable> inputParameters) {
        this.inputParameters = inputParameters;
    }

    public String getMethodBody() {
        return methodBody;
    }

    public void setMethodBody(final String methodBody) {
        this.methodBody = methodBody;
    }

    public CSXMLComment getComment() {
        return comment;
    }

    public void setComment(final CSXMLComment comment) {
        this.comment = comment;
    }

    public String getInterfaceStyledMethod() {
        this.isInterfaceMethod = true;
        return this.toString();
    }

    public void setIsSynchronized() {
        this.isSynchronized = true;
    }

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        if (comment.getContent() != null) {
            stringBuilder.append(comment.getContent()).append('\n');
        }
        stringBuilder.append('\t').append(accessModifier != null ? accessModifier : "");
        stringBuilder.append(' ')
                .append(returnType).append(' ').append(methodName).append('(');
        if (inputParameters != null) {
            for (int index = 0; index < inputParameters.size(); index++) {
                stringBuilder.append(inputParameters.get(index));
                if (index + 1 < inputParameters.size()) {
                    stringBuilder.append(',').append(' ');
                }
            }
        }
        if (!isInterfaceMethod && !isSynchronized) {
            stringBuilder.append(")");
            stringBuilder.append(" {\n");
            if (statements != null) {
                for (final Statement statement : statements) {
                    stringBuilder.append('\t').append(statement.toString()).append(statement.isRequireClosing()? ';' : "").append('\n');
                }
            } else {
                stringBuilder.append("//This method has no body");
            }
            stringBuilder.append("\n\t}");
        } else if (!isInterfaceMethod && isSynchronized) {
            stringBuilder.append(")");
            stringBuilder.append(" {\n\tlock (new Object()){\n ");
            if (statements != null) {
                for (final Statement statement : statements) {
                    stringBuilder.append('\t').append(statement.toString()).append(statement.isRequireClosing()? ';' : "").append('\n');
                }
            } else {
                stringBuilder.append("//This method has no body");
            }
            stringBuilder.append("\n\t\t}\n\t}");
        } else {
            stringBuilder.append(");\n");
        }


        //.append(methodBody);
        return stringBuilder.toString();
    }

    public List<Statement> getStatements() {
        return statements;
    }

    public void setStatements(final List<Statement> statements) {
        this.statements = statements;
    }

    public double getConversionTime() {
        return conversionTime;
    }

    public void setConversionTime(final double conversionTime) {
        this.conversionTime = conversionTime;
    }
}
